package cn.chinaflame.pagodas.service;

import cn.chinaflame.pagodas.enums.CodeEnum;
import cn.chinaflame.pagodas.handle.HandlerException;
import cn.chinaflame.pagodas.utils.ParamPreconditions;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author created by boming
 * @date 2018年1月16日 下午4:37:15
 */
public class JdbcPage<E> {


    private static final Logger log = LoggerFactory.getLogger(JdbcPage.class);

    //页大小
    private int pageSize;
    //页码
    private int pageIndex;
    //总页数
    private long count;
    private List<E> page;

    public JdbcPage(final String sql, int pageSize, int pageIndex, final JdbcTemplate jdbcTemplate, final Class<E> c) {

        ParamPreconditions.checkNotNull(jdbcTemplate, CodeEnum.FAIL.getCode(), "jdbctemplate is null");
        ParamPreconditions.checkArgument(pageSize > 0 && pageIndex > 0, CodeEnum.FAIL.getCode(), "页码或页数不能为负数");
        ParamPreconditions.checkNotEmpty(sql, CodeEnum.FAIL.getCode(), "查询sql不能为空");
        setPageIndex(pageIndex);
        setPageSize(pageSize);
        setPage(Lists.newArrayList());
        StringBuilder countSql = new StringBuilder();
        countSql.append("select count(*) from (").append(sql).append(") tab");
        setCount(jdbcTemplate.queryForObject(countSql.toString(), Long.class));
        StringBuilder pageSql = new StringBuilder();
        int limit = (pageIndex - 1) * pageSize;
        pageSql.append("select * from (").append(sql).append(") tab limit ").append(limit).append(",").append(pageSize);
        log.info("查询sql:{}", pageSql);
        List<Map<String, Object>> result = jdbcTemplate.queryForList(pageSql.toString());
        try {
            for (int i = 0; i < result.size(); i++) {
                E e = c.newInstance();
                for (Entry<String, Object> entry : result.get(i).entrySet()) {
                    Field f = e.getClass().getDeclaredField(entry.getKey());
                    if (f.getType().getSimpleName().equals("BigDecimal") && entry.getValue() != null) {
                        BigDecimal b = new BigDecimal(String.valueOf(entry.getValue()));
                        f.setAccessible(true);
                        f.set(e, b);
                    } else if (f.getType().getSimpleName().equals("Integer") && entry.getValue() != null) {
                        Integer b = Integer.valueOf(String.valueOf(entry.getValue()));
                        f.setAccessible(true);
                        f.set(e, b);
                    } else {
                        if (entry.getValue() != null) {
                            f.setAccessible(true);
                            f.set(e, String.valueOf(entry.getValue()));
                        }
                    }
                }
                page.add(e);
            }
        } catch (ReflectiveOperationException e) {
            throw new HandlerException(CodeEnum.FAIL.getCode(), "分页查询失败", "分页查询失败", e);
        }
    }

    /**
     * 获取总条数
     *
     * @param sql
     * @param jdbcTemplate
     * @return
     */
    public static long getCountBySql(final String sql, final JdbcTemplate jdbcTemplate) {
        ParamPreconditions.checkNotNull(jdbcTemplate, CodeEnum.FAIL.getCode(), "jdbctemplate is null");
        ParamPreconditions.checkNotEmpty(sql, CodeEnum.FAIL.getCode(), "查询sql不能为空");
        StringBuilder countSql = new StringBuilder();
        countSql.append("select count(*) from (").append(sql).append(") tab");
        return jdbcTemplate.queryForObject(countSql.toString(), Long.class);
    }

    public List<E> getPage() {
        return page;
    }

    public void setPage(List<E> page) {
        this.page = page;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getPageIndex() {
        return pageIndex;
    }

    public void setPageIndex(int pageIndex) {
        this.pageIndex = pageIndex;
    }

    public long getCount() {
        return count;
    }

    public void setCount(long count) {
        this.count = count;
    }

}
